1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
import { NextRequest, NextResponse } from "next/server";
import { Redis } from "@upstash/redis";
import { z } from "zod";
const responseValidation = z.union([
z.object({
data: z.object({
remainingReads: z.number().int().optional(),
secret: z.string(),
}),
}),
z.object({
error: z.string(),
}),
]);
const redis = Redis.fromEnv();
export default async function handler(req: NextRequest): Promise<NextResponse> {
try {
if (req.method !== "GET") {
return NextResponse.json({ error: "Method Not Allowed" }, { status: 405 });
}
const id = new URL(req.url).searchParams.get("id");
if (!id) {
return NextResponse.json({ error: "Missing `id` parameter" }, { status: 400 });
}
const redisKey = ["envshare", id].join(":");
const [data, _] = await Promise.all([
await redis.hgetall<{ secret: string; remainingReads: number | null }>(redisKey),
await redis.incr("envshare:metrics:reads"),
]);
if (!data) {
return NextResponse.json({ error: "Not Found" }, { status: 404 });
}
if (data.remainingReads !== null && data.remainingReads < 1) {
await redis.del(redisKey);
return NextResponse.json({ error: "Not Found" }, { status: 404 });
}
let remainingReads: number | null = null;
if (data.remainingReads !== null) {
// Decrement the number of reads and return the remaining reads
remainingReads = await redis.hincrby(redisKey, "remainingReads", -1);
}
return NextResponse.json({ data: { secret: data.secret, remainingReads: remainingReads ?? undefined } });
} catch (e) {
console.error(e);
return NextResponse.json({ error: "Internal Server Error" }, { status: 500 });
}
}
export const config = {
runtime: "edge",
};
|